我可以通过add_action将参数传递给我的函数吗?

时间:2010-05-16 10:32:56

标签: php wordpress

我可以这样做吗?将参数传递给我的函数?我已经研究过add_action doc但是没有弄清楚如何去做。传递两个参数的确切语法是什么样的。特别是如何通过文本&整数参数

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

更新

在我看来,它是通过do_action以某种方式完成的,但是怎么样? : - )

15 个答案:

答案 0 :(得分:39)

  我可以这样做吗?将参数传递给我的函数?

是的,你可以!诀窍在于您传递给add_action的函数类型以及您对do_action的期望。

  • “my_function_name”
  • array(instance,'instance_function_name')
  • “StaticClassName :: a_function_on_static_class'
  • 匿名
  • 拉姆达
  • 闭合

我们可以使用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>';
}

以下是关闭工作的简化示例

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

代理功能类

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

示例用法#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

示例用法#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

答案 1 :(得分:29)

而不是:

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

它应该是:

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

...其中2是参数个数,10是执行函数的优先级。您没有在add_action中列出您的参数。这最初让我失望了。您的功能如下所示:

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

add_action和function都在functions.php中,你在do_action中用模板文件(例如page.php)指定你的参数:

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

希望这有帮助。

答案 2 :(得分:17)

使用类

构建自定义WP函数

对于类来说这很容易,因为您可以使用构造函数设置对象变量,并在任何类方法中使用它们。举一个例子,这里是添加元框可以在类中工作的方法......

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

如果您认为__construct($arg)function functionname($arg)相同,那么您应该能够避免全局变量并将所需的所有信息传递给类对象中的任何函数。

在构建wordpress meta / plugins时,这些页面似乎是很好的参考点 - &gt;

答案 3 :(得分:6)

基本上do_action放在应该执行操作的位置,它需要一个名称加上你的自定义参数。

当您使用add_action调用该函数时,将do_action()的名称作为第一个参数传递,将函数名称作为第二个参数传递。如下所示:

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

这是执行的地方

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

希望有效。

答案 4 :(得分:2)

我遇到了同样的问题并通过使用全局变量解决了它。像这样:

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

function myfunction() {
    global $myvar;
}

有点草率但它有效。

答案 5 :(得分:2)

我使用PHP 5.3+的闭包。然后,我可以传递默认值,并且不使用全局变量。 (add_filter的例子)

...
$tt="try this";

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

答案 6 :(得分:2)

嗯,这已经过时了,但没有接受答案。恢复,以便谷歌搜索者有一些希望。

如果您有一个不接受这样的参数的现有add_action调用:

function my_function() {
  echo 100;
}

add_action('wp_footer', 'my_function');

您可以使用匿名函数将参数传递给该函数,如下所示:

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

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

根据您的使用情况,您可能需要使用不同形式的回调,甚至可能使用正确声明的函数,因为有时您可能会遇到范围问题。

答案 7 :(得分:2)

将数据传递到add_action函数的7种方法

  1. 通过do_action(如果您自己创建操作)
  2. wp_localize_script方法(如果您需要将数据传递给JavaScript)
  3. 在闭包/匿名/拉姆达函数中使用use
  4. 使用箭头功能(PHP 7.4 +)
  5. 使用add_filterapply_filters作为传输方式(聪明的方式)
  6. global$GLOBALS来限制范围(如果您不顾一切的话)
  7. 使用set_transientget_transient和其他功能作为交通工具(如果有特殊需求的话)

#1通过do_action

如果您可以访问触发操作的代码,请通过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方法

如果您需要将变量传递给JavaScript,这是最好的方法。

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"

基本相同,但没有wp_localize_script

functions.php

add_action( 'wp_enqueue_scripts', function(){
    echo <<<EOT
    <script> 
    window.my_data = { 'bar' : 'somedata', 'foo' : 'something else' };
    </script>;
    EOT;

    wp_enqueue_script( 'my_script', get_template_directory_uri() . '/assets/js/my-script.js', array( 'jquery' ), false, false );
}, 10, 1 );

#3在闭包/匿名/拉姆达函数中使用use

如果您无权访问触发操作的代码,则可以按以下步骤滑动数据(PHP 5.3 +):

$data1 = '1';
$data2 = '2';
$data3 = '3';

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

#4利用箭头功能(PHP 7.4 +)

与#3示例基本相同,但更为简洁,因为箭头函数涉及来自父作用域的变量,而没有使用use

$data1 = '1';
$data2 = '2';
$data3 = '3';

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

#5使用add_filterapply_filters作为交通工具

您可以使用add_filter创建一个函数,该函数将在您调用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'); 

我已经看到许多插件都采用了这种方法。

#6用global$GLOBALS(有意思的方式)破解范围

如果您不担心范围,请使用global示例1:

$data1 = '1';
$data2 = '2';
$data3 = '3';

function foo() {
    global $data1, $data2, $data3;

    echo $data1 . $data2 . $data3; // 123
}
add_action( 'init', 'foo' );

示例2 ,使用$GLOBALS代替global

$data1 = '1';
$data2 = '2';
$data3 = '3';

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

#7使用set_transientget_transientset_query_varget_query_var作为交通工具

示例1::假设有一个打印表单的短代码,随后通过AJAX提交并处理了该表单,并且来自表单的数据必须通过电子邮件发送,从shortcode参数中获取。

  1. 初始化简码
  2. 解析并打印简码,记住瞬态参数

-在Ajax处理程序内---

  1. 从瞬变中获取必需的参数并发送电子邮件。

示例2::在Wordpress 5.5推出之前,有些人已经在wp_query中将get/set_query_vars中的参数传递给了模板部分,这些参数可以用作好吧。

将它们混合并使用。干杯。

答案 8 :(得分:1)

我很久以前就写过wordpress插件,但是我去了Wordpress Codex,我认为这是可能的:http://codex.wordpress.org/Function_Reference/add_action

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

我认为你应该将它们作为数组传递。看一下“拿参数”的例子。

再见

答案 9 :(得分:0)

如果要将参数传递给可调用函数,而不是do_action,则可以调用匿名函数。示例:

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

您看到do_action('shutdown')不接受任何参数,但是routeRequests接受。

答案 10 :(得分:0)

function reset_header() {
    ob_start();
}
add_action('init', 'reset_header');

然后

reset_header();
wp_redirect( $approvalUrl);

更多信息https://tommcfarlin.com/wp_redirect-headers-already-sent/

答案 11 :(得分:0)

为什么不简单地这样:

function recent_post_by_author_related($author,$number_of_posts) {
    // some commands;
}

function recent_post_by_author() {
    recent_post_by_author_related($foo, $bar);
}
add_action('thesis_hook_before_post','recent_post_by_author')

答案 12 :(得分:0)

我今天遇到了同样的事情,由于这里的所有答案要么不清楚、不相关或过多,我想我会提供简单直接的答案。

就像这里最受欢迎的答案已经指出的那样,您应该使用匿名函数来实现您想要做的事情。但是,IMO 值得特别注意的是将操作的可用参数传递给您的函数的好处。

如果在某处,一个动作钩子是这样定义的:

do_action('cool_action_name', $first_param, $second_param);

您可以将 $first_param$second_param 的值传递给您自己的函数,并像这样添加您自己的参数:

add_action('cool_action_name', 
    function ($first_param, $second_param) {
        // Assuming you're working in a class, so $this is the scope.
        $this->your_cool_method($first_param, $second_param, 'something_else'); 
    }
);

然后您可以使用方法中的所有值,如下所示:

public function your_cool_method($first_param, $second_param, $something_else)
{
    // Do something with the params.
}

答案 13 :(得分:-1)

从本地范围FIRST传递变量,然后传递fn SECOND:

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

答案 14 :(得分:-2)

我已经编写了用于发送参数和过程的代码。

var child = SpreadsheetApp.open(parentFile.makeCopy("new name","parent Folder"));
saveFileIdSomehow(child.getId());
// do something with the child spreadsheet