can I pass arguments to my function through add_action?

后端 未结 13 2170
慢半拍i
慢半拍i 2020-11-29 01:07

can I do something like that? to pass arguments to my function? I already studied add_action doc but did not figure out how to do it. What the exact syntax to pass two argum

13条回答
  •  栀梦
    栀梦 (楼主)
    2020-11-29 01:28

    7 Ways to pass data to add_action function

    1. Through do_action (if you yourself create actions)
    2. wp_localize_script approach (if you need to pass data to JavaScript)
    3. Using use in Closures/Anonymous/Lamda functions
    4. Make use of arrow functions (PHP 7.4+)
    5. Use add_filter, apply_filters as a transport (clever way)
    6. Hack the scope with global or $GLOBALS (if you are desperate)
    7. Use set_transient, get_transient and other functions as a transport (in case of exotic necesities)

    #1 Through do_action

    if you have access to the code where the action fires, pass variables through do_action:

    /**
    * Our client code
    *
    * Here we recieve required variables.
    */
    function bar($data1, $data2, $data3) {
        /**
         * It's not necessary that names of these variables match 
         * the names of the variables we pass bellow in do_action.
         */
    
        echo $data1 . $data2 . $data3;
    }
    add_action( 'foo', 'bar', 10, 3 );
    
    /**
     * The code where action fires
     *
     * Here we pass required variables.
     */
    $data1 = '1';
    $data2 = '2';
    $data3 = '3';
    //...
    do_action( 'foo', $data1, $data2, $data3 /*, .... */ );
    

    #2 wp_localize_script approach

    if you need to pass variable to JavaScript, this is the best way of doing it.

    functions.php

    /**
     * Enqueue script
     */
    add_action( 'wp_enqueue_scripts', function() {
        wp_enqueue_script( 'my_script', get_template_directory_uri() . '/assets/js/my-script.js', array( 'jquery' ), false, false );
    } );
    
    /**
     * Pass data to the script as an object with name `my_data`
     */
    add_action( 'wp_enqueue_scripts', function(){
        wp_localize_script( 'my_script', 'my_data', [
            'bar' => 'some data',
            'foo' => 'something else'
        ] );
    } );
    

    my-script.js

    alert(my_data.bar); // "some data"
    alert(my_data.foo); // "something else"
    

    Basically the same but without wp_localize_script:

    functions.php

    add_action( 'wp_enqueue_scripts', function(){
        echo << 
        window.my_data = { 'bar' : 'somedata', 'foo' : 'something else' };
        ;
        EOT;
    
        wp_enqueue_script( 'my_script', get_template_directory_uri() . '/assets/js/my-script.js', array( 'jquery' ), false, false );
    }, 10, 1 );
    

    #3 Using use in Closures/Anonymous/Lamda functions

    if you don't have access to the code where the action fires you can slip the data as follows (PHP 5.3+):

    $data1 = '1';
    $data2 = '2';
    $data3 = '3';
    
    add_action( 'init', function() use ($data1, $data2, $data3) {
        echo $data1 . $data2 . $data3; // 123
    });
    

    #4 Make use of arrow functions (PHP 7.4+)

    Basically the same as the #3 example but more concise, as the arrow functions involve variables from the parent scope without using use:

    $data1 = '1';
    $data2 = '2';
    $data3 = '3';
    
    add_action( 'init', fn() => print( $data1 . $data2 . $data3 ) ); // prints "123"
    

    #5 Use add_filter, apply_filters as a transport

    You can create a function with add_filter that will return value when you call apply_filters:

    /**
     * Register the data with the filter functions
     */
    add_filter( 'data_1', function() { return '1'; } );
    add_filter( 'data_2', function() { return '2'; } );
    add_filter( 'data_3', fn() => '3' ); // or in concise way with arrow function
    
    function foo() {
        /**
         * Get the previously registered data
         */
        echo apply_filters( 'data_1', null ) . 
             apply_filters( 'data_2', null ) . 
             apply_filters( 'data_3', null ); // 123
    }
    add_action( 'init', 'foo'); 
    

    I have seen the approach applied in many plugins.

    #6 Hack the scope with global or $GLOBALS (kiddy way)

    If you don't worry about the scope, use global, example #1:

    $data1 = '1';
    $data2 = '2';
    $data3 = '3';
    
    function foo() {
        global $data1, $data2, $data3;
    
        echo $data1 . $data2 . $data3; // 123
    }
    add_action( 'init', 'foo' );
    

    Example #2 Using $GLOBALS instead of global

    $data1 = '1';
    $data2 = '2';
    $data3 = '3';
    
    function foo() {
        echo $GLOBALS['data1'] . $GLOBALS['data2'] . $GLOBALS['data3']; // 123
    }
    add_action( 'init', 'foo' );
    

    #7 Use set_transient, get_transient, set_query_var, get_query_var as a transport

    Example #1: Let's say there is a shortcode that prints a form, that subsequently gets submitted and handled via AJAX, and the data is coming from the form must be sent by email that should be gotten from the shortcode parameters.

    1. Init shortcode
    2. Parse and print shortcode, remember parameters to transients

    --- Within Ajax handler ---

    1. Get required parameters from the transient and send the email.

    Example #2: Before Wordpress 5.5 came out, some people had passed parameters within wp_query by get/set_query_vars to pass them to the template parts, these can be used as well.

    Mix them up and use. Cheers.

提交回复
热议问题