ผ่านพารามิเตอร์เพื่อกรองและฟังก์ชั่นการกระทำ


52

เป็นวิธีที่จะส่งผ่านพารามิเตอร์ของตัวเองให้กับฟังก์ชั่นในหรือadd_filter add_actionตัวอย่างเช่นดูในรหัสต่อไปนี้:

function my_content($content, $my_param)
{
do something...
using $my_param here ...
return $content;
}
add_filter('the_content', 'my_content', 10, 1);

ฉันสามารถส่งพารามิเตอร์ของตัวเองได้หรือไม่? สิ่งที่ต้องการ:

add_filter('the_content', 'my_content($my_param)', 10, 1)

หรือ

add_filter('the_content', 'my_content', 10, 1, $my_param)

คำตอบ:


78

โดยค่าเริ่มต้นนี้เป็นไปไม่ได้ มีวิธีแก้ไขหากคุณใช้วิธี OOP
คุณสามารถสร้างคลาสเพื่อเก็บค่าที่คุณต้องการใช้ในภายหลัง

ตัวอย่าง:

/**
 * Stores a value and calls any existing function with this value.
 */
class WPSE_Filter_Storage
{
    /**
     * Filled by __construct(). Used by __call().
     *
     * @type mixed Any type you need.
     */
    private $values;

    /**
     * Stores the values for later use.
     *
     * @param  mixed $values
     */
    public function __construct( $values )
    {
        $this->values = $values;
    }

    /**
     * Catches all function calls except __construct().
     *
     * Be aware: Even if the function is called with just one string as an
     * argument it will be sent as an array.
     *
     * @param  string $callback Function name
     * @param  array  $arguments
     * @return mixed
     * @throws InvalidArgumentException
     */
    public function __call( $callback, $arguments )
    {
        if ( is_callable( $callback ) )
            return call_user_func( $callback, $arguments, $this->values );

        // Wrong function called.
        throw new InvalidArgumentException(
            sprintf( 'File: %1$s<br>Line %2$d<br>Not callable: %3$s',
                __FILE__, __LINE__, print_r( $callback, TRUE )
            )
        );
    }
}

ตอนนี้คุณสามารถเรียกชั้นเรียนด้วยฟังก์ชั่นใด ๆ ที่คุณต้องการ - ถ้าฟังก์ชั่นนั้นอยู่ที่ใดที่หนึ่งมันจะถูกเรียกพร้อมกับพารามิเตอร์ที่เก็บไว้ของคุณ

มาสร้างฟังก์ชั่นตัวอย่าง ...

/**
 * Filter function.
 * @param  array $content
 * @param  array $numbers
 * @return string
 */
function wpse_45901_add_numbers( $args, $numbers )
{
    $content = $args[0];
    return $content . '<p>' . implode( ', ', $numbers ) . '</p>';
}

... และใช้งานครั้งเดียว ...

add_filter(
    'the_content',
    array (
        new WPSE_Filter_Storage( array ( 1, 3, 5 ) ),
        'wpse_45901_add_numbers'
    )
);

… และอีกครั้ง …

add_filter(
    'the_content',
    array (
        new WPSE_Filter_Storage( array ( 2, 4, 6 ) ),
        'wpse_45901_add_numbers'
    )
);

เอาท์พุท:

ป้อนคำอธิบายรูปภาพที่นี่

กุญแจสำคัญคือการใช้ซ้ำได้ : คุณสามารถนำคลาสมาใช้ซ้ำได้

PHP 5.3 ขึ้นไป

หากคุณสามารถใช้ PHP เวอร์ชัน 5.3 หรือการปิดที่ใหม่กว่าจะทำให้ง่ายขึ้นมาก:

$param1 = '<p>This works!</p>';
$param2 = 'This works too!';

add_action( 'wp_footer', function() use ( $param1 ) {
        echo $param1;
    }, 11 
);
add_filter( 'the_content', function( $content ) use ( $param2 ) {
        return t5_param_test( $content, $param2 );
    }, 12
);

/**
 * Add a string to post content
 *
 * @param  string $content
 * @param  string $string This is $param2 in our example.
 * @return string
 */
function t5_param_test( $content, $string )
{
    return "$content <p><b>$string</b></p>";
}

ข้อเสียคือคุณไม่สามารถเขียนการทดสอบหน่วยสำหรับการปิด 


17
คุณไม่เพียงได้รับคะแนนโหวตสำหรับคำตอบที่มีคุณภาพสำหรับปัญหาที่ควรมีวิธีแก้ปัญหาในตัวภายใน WP coreคุณยังจะได้รับหนึ่งสำหรับการกลับมาอีกห้าเดือนต่อมาเพื่ออัปเดตคำตอบของคุณด้วยตัวอย่างการปิด PHP 5.3+
อดัม

1
คำตอบที่ยอดเยี่ยม! แต่ฉันจะทำอย่างไรเพื่อลบตัวกรองนี้ที่สร้างโดยฟังก์ชั่นนิรนามนี้ในภายหลัง
Vinicius Tavares

2
@ViniciusTavares คุณทำไม่ได้ คิดก่อนใช้ :)
fuxia

5
โปรดทราบว่าหากคุณบันทึกฟังก์ชันที่ไม่ระบุชื่อไปยังตัวแปร (เช่น$func = function() use ( $param1 ) { $param1; };และadd_action( $func, 11);) คุณสามารถลบออกได้ผ่านทางremove_action( $func, 11 );
bonger

1
แต่ไม่แนะนำให้ใช้ฟังก์ชั่นที่ไม่ระบุชื่อในปลั๊กอินหรือธีมที่คุณกำลังเปิดตัวสู่โลก (คุณสามารถใช้มันในโครงการของคุณเอง) ปัญหานี้คือคุณจะไม่สามารถปลดล็อกได้ สิ่งที่คุณเคยตัดสินใจที่จะไปด้วยควรจะไม่สามารถทำได้ในภายหลัง
Mueyiwa Moses Ikomi

1

สร้างฟังก์ชั่นที่มีอาร์กิวเมนต์ที่ต้องการซึ่งส่งคืนฟังก์ชัน ผ่านฟังก์ชั่นนี้ (ฟังก์ชั่นที่ไม่ระบุชื่อหรือที่รู้จักกันว่าการปิด) ไปยังเบ็ด wp

แสดงที่นี่สำหรับการแจ้งเตือนผู้ดูแลระบบในแบ็กเอนด์ WordPress

public function admin_notice_func( $message = '')
{
$class = 'error';
    $output = sprintf('<div class="%s"><p>%s</p></div>',$class, $message);
    $func = function() use($output) { print $output; };
    return $func;
}
$func = admin_notice_func('Message');
add_action('admin_notices', $func);


1

ฉันรู้ว่าเวลาผ่านไปแล้ว แต่ฉันมีปัญหากับการส่งพารามิเตอร์ของตัวเองจนกระทั่งพบว่าพารามิเตอร์ที่สี่ใน add_filter คือจำนวนพารามิเตอร์ที่ส่งผ่านรวมถึงเนื้อหาที่จะเปลี่ยน ดังนั้นหากคุณผ่านพารามิเตอร์เพิ่มเติม 1 รายการหมายเลขควรเป็น2และไม่ใช่ 1 ในกรณีของคุณ

add_filter('the_content', 'my_content', 10, 2, $my_param)

และการใช้

function my_content($content, $my_param) {...}

1

วิธีที่ถูกต้องสั้นและมีประสิทธิภาพมากที่สุดในการส่งผ่านจำนวนอาร์กิวเมนต์ไปยังตัวกรอง WP และการกระทำใด ๆ จาก @Wesam Alalem ที่นี่ซึ่งใช้การปิด

ฉันจะเพิ่มเฉพาะที่คุณสามารถทำให้มันชัดเจนยิ่งขึ้นและมีความยืดหยุ่นมากขึ้นโดยการแยกวิธีการทำจริงจากการปิดที่ไม่ระบุชื่อ สำหรับสิ่งนี้คุณเพียงแค่เรียกเมธอดจากการปิดดังนี้ (ตัวอย่างที่แก้ไขจาก @Wesam Alalem answer)

วิธีนี้คุณสามารถเขียนตรรกะที่มีความยาวหรือซับซ้อนได้ตามที่คุณต้องการนอกเหนือจากการปิดที่คุณใช้เพื่อโทรหาผู้ปฏิบัติจริง

// ... inside some class

private function myMethod() {
    $my_param = 'my theme name';
    add_filter('the_content', function ($content) use ($my_param) {
        // This is the anonymous closure that allows to pass 
        // whatever number of parameters you want via 'use' keyword.
        // This is just oneliner.
        // $my_param is available for you now via 'use' keyword above
        return $this->doThings($content, $my_param);
    }, 10, 2);
}

private function doThings($content, $my_param) {
    // Call here some other method to do some more things
    // however complicated you want.
    $morethings = '';
    if ($content = 'some more things') {
        $morethings = (new MoreClass())->get();
    }
    return $my_param . ':<br>' . $content . $morethings;
}

0

หากคุณสร้างเบ็ดของคุณเองนี่คือตัวอย่าง

// lets say we have three parameters  [ https://codex.wordpress.org/Function_Reference/add_filter ]
add_filter( 'filter_name', 'my_func', 10, 3 );
my_func( $first, $second, $third ) {
  // code
}

จากนั้นใช้เบ็ด:

// [ https://codex.wordpress.org/Function_Reference/apply_filters ]
echo apply_filters( 'filter_name', $first, $second, $third );

สิ่งนี้ไม่ส่งผ่านข้อมูลจากการลงทะเบียนไปยังการโทรกลับ มันเพิ่งบอกว่าพารามิเตอร์โทรกลับสามารถยอมรับจำนวน
fuxia

@fuxia คุณสามารถแนะนำการเปลี่ยนแปลงอย่างง่าย ๆ เพื่อให้ข้อมูลได้รับการส่งผ่านหรือไม่ จะเพียงแค่ตรึงค่าพารามิเตอร์หลังจาก3?
SherylHohman

0

คุณสามารถใช้ทั่วโลกได้ใช่มั้ย

  global $my_param;

สิ่งนี้ไม่ได้ให้คำตอบสำหรับคำถาม เมื่อคุณมีเพียงพอชื่อเสียงคุณจะสามารถที่จะแสดงความคิดเห็นในโพสต์ใด ๆ ; แทนที่จะให้คำตอบที่ไม่จำเป็นต้องชี้แจงจากผู้ถาม - จากการรีวิว
cjbj

@cjbj จริง ๆ แล้วมันทำ คำถามคือพารามิเตอร์สามารถถูกส่งผ่านไปยัง "ฟังก์ชั่น" ที่อยู่ใน add_filter หรือ add_action ไม่ชัดเจนหากผู้ใช้ต้องการส่งผ่านมันในฟังก์ชั่น add_filter หรือ add_action เองแม้ว่าจะเป็นข้อสันนิษฐานก็ตาม :)
samjco

0

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

ตัวอย่างเช่น:

ฉันมีฟังก์ชั่นเดียวในการแปลชื่อเนื้อหาและข้อความที่ตัดตอนมาจากโพสต์ของฉัน ดังนั้นฉันต้องผ่านฟังก์ชั่นหลักนี้บางข้อโต้แย้งว่าใครโทร

add_filter( 'the_title', function( $text ) { 
    return translate_text( $text, 'title', 'pl' );
});

add_filter( 'the_content', function( $text ) { 
    return translate_text( $text, 'content', 'pl' );
});

add_filter( 'the_excerpt', function( $text ) { 
    return translate_text( $text, 'excerpt', 'pl' );
});

ดังนั้นฟังก์ชั่นหลักtranslate_textได้รับพารามิเตอร์มากเท่าที่ฉันต้องการเพียงเพราะฉันได้ผ่านฟังก์ชั่นที่ไม่ระบุชื่อเป็นการโทรกลับ


-1

ฉันหวังว่าจะทำแบบเดียวกัน แต่เนื่องจากมันเป็นไปไม่ได้ฉันเดาว่าวิธีแก้ปัญหาง่ายๆคือการเรียกใช้ฟังก์ชันอื่นเช่น add_filter('the_content', 'my_content_filter', 10, 1);

จากนั้น my_content_filter () สามารถเรียก my_content () ผ่านการโต้แย้งใด ๆ ที่มันต้องการ

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