can I pass arguments to my function through add_action?

给你一囗甜甜゛ 提交于 2019-11-27 03:20:29

can I do something like that? to pass arguments to my function?

Yes you can! The trick really is in what type of function you pass to add_action and what you expect from do_action.

  • ‘my_function_name’
  • array( instance, ‘instance_function_name’)
  • ‘StaticClassName::a_function_on_static_class'
  • anonymous
  • lambda
  • closure

We can do it with a closure.

// custom args for hook

$args = array (
    'author'        =>  6, // id
    'posts_per_page'=>  1, // max posts
);

// subscribe to the hook w/custom args

add_action('thesis_hook_before_post', 
           function() use ( $args ) { 
               recent_post_by_author( $args ); });


// trigger the hook somewhere

do_action( 'thesis_hook_before_post' );


// renders a list of post tiles by author

function recent_post_by_author( $args ) {

    // merge w/default args
    $args = wp_parse_args( $args, array (
        'author'        =>  -1,
        'orderby'       =>  'post_date',
        'order'         =>  'ASC',
        'posts_per_page'=>  25
    ));

    // pull the user's posts
    $user_posts = get_posts( $args );

    // some commands
    echo '<ul>';
    foreach ( $user_posts as $post ) {
        echo "<li>$post->post_title</li>";
    }
    echo '</ul>';
}

Here is a simplified example of a closure working

$total = array();

add_action('count_em_dude', function() use (&$total) { $total[] = count($total); } );

do_action ('count_em_dude' );
do_action ('count_em_dude' );
do_action ('count_em_dude' );
do_action ('count_em_dude' );
do_action ('count_em_dude' );
do_action ('count_em_dude' );
do_action ('count_em_dude' );

echo implode ( ', ', $total ); // 0, 1, 2, 3, 4, 5, 6

Anonymous vs. Closure

add_action ('custom_action', function(){ echo 'anonymous functions work without args!'; } ); //

add_action ('custom_action', function($a, $b, $c, $d){ echo 'anonymous functions work but default args num is 1, the rest are null - '; var_dump(array($a,$b,$c,$d)); } ); // a

add_action ('custom_action', function($a, $b, $c, $d){ echo 'anonymous functions work if you specify number of args after priority - '; var_dump(array($a,$b,$c,$d)); }, 10, 4 ); // a,b,c,d

// CLOSURE

$value = 12345;
add_action ('custom_action', function($a, $b, $c, $d) use ($value) { echo 'closures allow you to include values - '; var_dump(array($a,$b,$c,$d, $value)); }, 10, 4 ); // a,b,c,d, 12345

// DO IT!

do_action( 'custom_action', 'aa', 'bb', 'cc', 'dd' ); 

Proxy Function Class

class ProxyFunc {
    public $args = null;
    public $func = null;
    public $location = null;
    public $func_args = null;
    function __construct($func, $args, $location='after', $action='', $priority = 10, $accepted_args = 1) {
        $this->func = $func;
        $this->args = is_array($args) ? $args : array($args);
        $this->location = $location;
        if( ! empty($action) ){
            // (optional) pass action in constructor to automatically subscribe
            add_action($action, $this, $priority, $accepted_args );
        }
    }
    function __invoke() {
        // current arguments passed to invoke
        $this->func_args = func_get_args();

        // position of stored arguments
        switch($this->location){
            case 'after':
                $args = array_merge($this->func_args, $this->args );
                break;
            case 'before':
                $args = array_merge($this->args, $this->func_args );
                break;
            case 'replace':
                $args = $this->args;
                break;
            case 'reference':
                // only pass reference to this object
                $args = array($this);
                break;
            default:
                // ignore stored args
                $args = $this->func_args;
        }

        // trigger the callback
        call_user_func_array( $this->func, $args );

        // clear current args
        $this->func_args = null;
    }
}

Example Usage #1

$proxyFunc = new ProxyFunc(
    function() {
        echo "<pre>"; print_r( func_get_args() ); wp_die();
    },
    array(1,2,3), 'after'
);

add_action('TestProxyFunc', $proxyFunc );
do_action('TestProxyFunc', 'Hello World', 'Goodbye'); // Hello World, 1, 2, 3

Example Usage #2

$proxyFunc = new ProxyFunc(
    function() {
        echo "<pre>"; print_r( func_get_args() ); wp_die();
    },                  // callback function
    array(1,2,3),       // stored args
    'after',            // position of stored args
    'TestProxyFunc',    // (optional) action
    10,                 // (optional) priority
    2                   // (optional) increase the action args length.
);
do_action('TestProxyFunc', 'Hello World', 'Goodbye'); // Hello World, Goodbye, 1, 2, 3

Instead of:

add_action('thesis_hook_before_post','recent_post_by_author',10,'author,2')

it should be:

add_action('thesis_hook_before_post','recent_post_by_author',10,2)

...where 2 is the number of arguments and 10 is the priority in which the function will be executed. You don't list your arguments in add_action. This initially tripped me up. Your function then looks like this:

function function_name ( $arg1, $arg2 ) { /* do stuff here */ }

Both the add_action and function go in functions.php and you specify your arguments in the template file (page.php for example) with do_action like so:

do_action( 'name-of-action', $arg1, $arg2 );

Hope this helps.

Build custom WP functions with classes

This is easy with classes, as you can set object variables with the constructor, and use them in any class method. So for an example, here's how adding meta boxes could work in classes...

// Array to pass to class
$data = array(
    "meta_id" => "custom_wp_meta",
    "a" => true,
    "b" => true,
    // etc...
);

// Init class
$var = new yourWpClass ($data);

// Class
class yourWpClass {

    // Pass $data var to class
    function __construct($init) {
        $this->box = $init; // Get data in var
        $this->meta_id = $init["meta_id"];
        add_action( 'add_meta_boxes', array(&$this, '_reg_meta') );
    }
    public function _reg_meta() {
        add_meta_box(
            $this->meta_id,
            // etc ....
        );
    }
}

If you consider __construct($arg) the same as function functionname($arg) then you should be able to avoid global variables and pass all the information you need through to any functions in the class object.

These pages seem to be good points of reference when building wordpress meta / plugins ->

hollsk

Basically the do_action is placed where the action should be executed, and it needs a name plus your custom parameters.

When you come to call the function using add_action, pass the name of your do_action() as your first argument, and the function name as the second. So something like:

function recent_post_by_author($author,$number_of_posts) {
  some commands;
}
add_action('get_the_data','recent_post_by_author',10,'author,2');

This is where it's executed

do_action('get_the_data',$author,$number_of_posts);

Should hopefully work.

I ran into the same issue and solved it by using global variables. Like so:

global $myvar;
$myvar = value;
add_action('hook', 'myfunction');

function myfunction() {
    global $myvar;
}

A bit sloppy but it works.

I use closure for PHP 5.3+. I can then pass the default values and mine without globals. (example for add_filter)

...
$tt="try this";

add_filter( 'the_posts', function($posts,$query=false) use ($tt) {
echo $tt;
print_r($posts);
return  $posts;
} );

Well, this is old, but it has no accepted answer. Reviving so that Google searchers have some hope.

If you have an existing add_action call that doesn't accept arguments like this:

function my_function() {
  echo 100;
}

add_action('wp_footer', 'my_function');

You can pass an argument to that function by using an anonymous function as the callback like this:

function my_function($number) {
  echo $number;
}

$number = 101;
add_action('wp_footer', function() { global $number; my_function($number); });

Depending on your use case, you might need to use different forms of callback, possibly even using properly declared functions, as sometimes you may encounter trouble with scope.

I've wrote wordpress plugin long time ago, but I went to Wordpress Codex and I think that's possible: http://codex.wordpress.org/Function_Reference/add_action

<?php add_action( $tag, $function_to_add, $priority, $accepted_args ); ?> 

I think you should pass them as an array. Look under examples "take arguments".

Bye

If you want to pass parameters to the callable function, instead of the do_action, you can call an anonymous function. Example:

// Route Web Requests
add_action('shutdown', function() {
    Router::singleton()->routeRequests('app.php');
});

You see that do_action('shutdown') don't accept any parameters, but routeRequests does.

Brandonian

Pass in vars from the local scope FIRST, then pass the fn SECOND:

$fn = function() use($pollId){ 
   echo "<p>NO POLLS FOUND FOR POLL ID $pollId</p>"; 
};
add_action('admin_notices', $fn);

I have made a code to send parameters and process.

function recibe_data_post() {

$post_data = $_POST;

if (isset($post_data)) {

    if (isset($post_data['lista_negra'])) {

        $args = array (
            'btn'  =>  'lista_negra',
            'estado'=>  $post_data['lista_negra'],
        );

        add_action('template_redirect',
                   function() use ( $args ) {
                       recibe_parametros_btn( $args ); });
    }
    if (isset($post_data['seleccionado'])) {
        $args = array (
            'btn'  =>  'seleccionado',
            'estado'=>  $post_data['seleccionado'],
        );

        add_action('template_redirect',
                   function() use ( $args ) {
                       recibe_parametros_btn( $args ); });

        }
    }
}

    add_action( 'init', 'recibe_data_post' );

function recibe_parametros_btn( $args ) {

$data_enc = json_encode($args);
$data_dec = json_decode($data_enc);

$btn = $data_dec->btn;
$estado = $data_dec->estado;

fdav_procesa_botones($btn, $estado);

}

function fdav_procesa_botones($btn, int $estado) {

$post_id = get_the_ID();
$data = get_post($post_id);

if ( $estado == 1 ) {
    update_field($btn, 0, $post_id);
    } elseif ( $estado == 0 ) {
       update_field($btn, 1, $post_id);
    }

}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!