Truyền tham số cho các hàm lọc và hành động


52

Là một cách để truyền tham số của riêng tôi cho hàm trong add_filterhoặc add_action. Ví dụ, hãy xem đoạn mã sau:

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

Tôi có thể vượt qua tham số của riêng tôi? cái gì đó như:

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

hoặc là

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

Câu trả lời:


78

Theo mặc định, điều này là không thể. Có cách giải quyết nếu bạn làm theo cách OOP.
Bạn có thể tạo một lớp để lưu trữ các giá trị bạn muốn sử dụng sau này.

Thí dụ:

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

Bây giờ bạn có thể gọi lớp với bất kỳ hàm nào bạn muốn - nếu hàm tồn tại ở đâu đó, nó sẽ được gọi với các tham số được lưu trữ của bạn.

Hãy tạo một chức năng demo

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

Tập và sử dụng nó một lần

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

… Và một lần nữa …

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

Đầu ra:

nhập mô tả hình ảnh ở đây

Chìa khóa là khả năng sử dụng lại : Bạn có thể sử dụng lại lớp (và trong các ví dụ của chúng tôi cũng là hàm).

PHP 5.3 trở lên

Nếu bạn có thể sử dụng phiên bản PHP 5.3 hoặc các lần đóng mới hơn sẽ giúp việc đó dễ dàng hơn nhiều:

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

Nhược điểm là bạn không thể viết bài kiểm tra đơn vị cho việc đóng cửa. 


17
Bạn không chỉ nhận được một phiếu bầu cho câu trả lời chất lượng cho một vấn đề cần có giải pháp tích hợp trong lõi WP , bạn còn nhận được một câu trả lời sau năm tháng để cập nhật câu trả lời của bạn với ví dụ đóng cửa PHP 5.3+.
Adam

1
Câu trả lời tuyệt vời! Nhưng làm thế nào tôi có thể làm để loại bỏ bộ lọc này được tạo bởi chức năng ẩn danh này sau này?
Vinicius Tavares

2
@ViniciusTavares Bạn không thể. Hãy suy nghĩ trước khi bạn sử dụng nó. :)
fuxia

5
Lưu ý rằng nếu bạn lưu hàm ẩn danh vào một biến (ví dụ $func = function() use ( $param1 ) { $param1; };add_action( $func, 11);) thì bạn có thể xóa nó quaremove_action( $func, 11 );
bonger

1
Nhưng không nên sử dụng các chức năng ẩn danh trên các plugin hoặc chủ đề bạn đang phát hành ra thế giới (bạn có thể sử dụng chúng cho các dự án của riêng bạn). Vấn đề với điều này là bạn sẽ không thể gỡ chúng ra. Những gì đã từng tiếp cận bạn quyết định đi cùng sẽ không thể thực hiện được sau này.
Mueyiwa Moses Ikomi

1

Tạo một hàm với các đối số cần thiết trả về một hàm. Truyền hàm này (hàm ẩn danh, còn được gọi là đóng) cho hook wp.

Hiển thị ở đây cho một thông báo quản trị trong phụ trợ 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

Sử dụng các hàm ẩn danh php :

$my_param = 'my theme name';
add_filter('the_content', function ($content) use ($my_param) {
    //$my_param is available for you now
    if (is_page()) {
        $content = $my_param . ':<br>' . $content;
    }
    return $content;
}, 10, 1);

1

Tôi biết thời gian đã trôi qua, nhưng tôi gặp một số vấn đề với việc truyền tham số của riêng mình cho đến khi tôi thấy rằng tham số thứ 4 trong add_filter là số lượng tham số được truyền bao gồm cả nội dung cần thay đổi. Vì vậy, nếu bạn vượt qua 1 tham số bổ sung, số phải là 2 chứ không phải 1 trong trường hợp của bạn

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

và sử dụng

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

1

Cách chính xác, thực sự ngắn và hiệu quả nhất để chuyển bất kỳ số lượng đối số nào cho các bộ lọc và hành động WP là từ @Wesam Alalem ở đây , sử dụng bao đóng.

Tôi chỉ nói thêm rằng bạn có thể làm cho nó rõ ràng hơn và linh hoạt hơn nhiều bằng cách tách phương thức người thực sự khỏi việc đóng ẩn danh. Đối với điều này, bạn chỉ cần gọi phương thức từ bao đóng như sau (ví dụ sửa đổi từ câu trả lời @Wesam Alalem).

Bằng cách này, bạn có thể viết logic dài hoặc phức tạp như bạn muốn từ vựng bên ngoài bao đóng mà bạn sử dụng để gọi người thực hiện.

// ... 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

nếu bạn tạo móc của riêng bạn, đây là ví dụ.

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

sau đó thực hiện hook:

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

Điều này không chuyển thông tin từ đăng ký để gọi lại. Nó chỉ cho biết có bao nhiêu tham số gọi lại có thể chấp nhận.
fuxia

@fuxia, bạn có thể đề xuất một thay đổi đơn giản để thông tin được thông qua không? Người ta sẽ giải quyết các giá trị param sau 3?
SherylHohman

0

Bạn luôn có thể sử dụng toàn cầu phải không?

  global $my_param;

Điều này không cung cấp một câu trả lời cho câu hỏi. Một khi bạn có đủ danh tiếng, bạn sẽ có thể nhận xét về bất kỳ bài đăng nào ; thay vào đó, cung cấp câu trả lời không yêu cầu làm rõ từ người hỏi . - Từ đánh giá
cjbj

@cjbj Thật ra là có. Câu hỏi đặt ra là các tham số có thể được chuyển đến "hàm" có trong add_filter hoặc add_action. Không rõ liệu người dùng muốn truyền nó vào hàm add_filter hay add_action mặc dù đó là giả định. :)
samjco

0

Mặc dù gọi một hàm trực tiếp, hãy thực hiện điều này theo cách thanh lịch hơn: chuyển một hàm ẩn danh dưới dạng gọi lại.

Ví dụ:

Tôi có một chức năng duy nhất để dịch tiêu đề, nội dung và đoạn trích từ bài viết của tôi. Vì vậy, tôi cần chuyển đến chức năng chính này một số đối số cho biết ai đang gọi.

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

Vì vậy, hàm chính translate_textnhận được nhiều tham số như tôi muốn, chỉ vì tôi đã truyền một hàm ẩn danh dưới dạng gọi lại.


-1

Tôi đã hy vọng làm điều tương tự nhưng vì không thể, tôi đoán một cách giải quyết đơn giản là gọi một chức năng khác như add_filter('the_content', 'my_content_filter', 10, 1);

sau đó my_content_filter () chỉ có thể gọi my_content () truyền bất kỳ đối số nào nó muốn.

Licensed under cc by-sa 3.0 with attribution required.