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

Posted

技术标签:

【中文标题】我可以通过 add_action 将参数传递给我的函数吗?【英文标题】:can I pass arguments to my function through add_action? 【发布时间】:2011-02-20 01:32:03 【问题描述】:

我可以这样做吗?将参数传递给我的函数?我已经研究过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 以某种方式完成的,但如何? :-)

【问题讨论】:

【参考方案1】:

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

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

‘my_function_name’ 数组(实例,'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

匿名与封闭

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

【讨论】:

对于使用ProxyFunc 方法的人:如果您的do_action 没有传递任何args,那么new ProxyFunc(...) 的最后一个参数必须作为0 传递。否则你的function 会得到一个空字符串作为第一个参数。 此响应的第一部分(参考关闭)是毫无疑问的答案。【参考方案2】:

代替:

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 中,您可以在模板文件(例如 page.php)中使用 do_action 指定参数,如下所示:

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

希望这会有所帮助。

【讨论】:

谢谢 Bart - 你刚刚让我免于陷入闭包/匿名函数漏洞,哈哈【参考方案3】:

使用类构建自定义 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 元/插件时,这些页面似乎是很好的参考点 ->

http://www.deluxeblogtips.com/2010/05/howto-meta-box-wordpress.html https://gist.github.com/1880770

【讨论】:

如果你不控制对 do_action 的调用,这是必须的 Word Press 插件的编码方式。很高兴看到这个建议!【参考方案4】:

基本上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);

希望能奏效。

【讨论】:

我尝试了你的建议,但是 do_action。我相信 do_action 是由 Thesis 处理的,我不应该碰它...... 所以我认为 thesis_hook_before_post 是您添加的自定义钩子,它已经与动作相关联?是否值得组合您的操作,或添加额外的操作?抱歉,这并没有让您很快接近答案,但是 WP 挂钩系统中的代码往往很快就会变得非常混乱,因此很难挑选出需要的东西。 我不知道如何在现有论文一中添加一些操作。我会说不值得这样做【参考方案5】:

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

    通过do_action(如果您自己创建操作) wp_localize_script 方法(如果需要将数据传递给 javascript) 在闭包/匿名/Lamda 函数中使用 use 使用箭头函数 (PHP 7.4+) 使用add_filterapply_filters 作为传输(聪明的方式) 使用global$GLOBALS 破解范围(如果您不顾一切) 使用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 在闭包/匿名/Lamda 函数中使用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 提交和处理,来自表单的数据必须通过电子邮件发送从简码参数中获取。

    初始化简码 解析和打印简码,记住瞬态参数

--- 在 Ajax 处理程序中 ---

    从瞬态中获取所需参数并发送电子邮件。

示例#2:在Wordpress 5.5出来之前,有些人在wp_query中通过get/set_query_vars传递参数给模板部分,这些也可以使用。 p>

混合起来使用。干杯。

【讨论】:

【参考方案6】:

首先从本地范围传入 vars,然后传递 fn SECOND:

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

【讨论】:

【参考方案7】:

我对 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;
 );

【讨论】:

感谢 Miguel,匿名函数(闭包)为我提供了操作和过滤器。【参考方案8】:

嗯,这是旧的,但它没有被接受的答案。复兴让谷歌搜索者有一些希望。

如果您有一个不接受此类参数的现有 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); );

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

【讨论】:

解释简单,通俗易懂。谢谢。【参考方案9】:

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

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

我认为您应该将它们作为数组传递。查看“接受参数”的示例。

再见

【讨论】:

在问我的问题之前,我按照您的建议做了。我不知道如何传递文本和整数参数。 哦,我明白了。我没有注意到它必须是(int)。对不起。好吧,您通常不通过 do_action_ref_array 传递参数吗?我的意思是你首先声明你的动作,然后你将它与 do_action 一起使用。 我可能可以用不同的方式编写代码,但如果我想在其他地方重用该函数,能够将一些参数传递给它会很好,不是吗 好的,但是 add_action 函数,因为我可以更仔细地阅读 Codex 来理解,它只是一种通过动作将你的函数连接到系统的方法,所以我不认为是它的设计接受更多的论点。在函数的定义中,您可以使用参数参数,但您必须使用 do_action 或 do_action_ref_array 传递实际参数。我当然可能是错的。但如果有办法,对不起,我不知道。【参考方案10】:

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

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

function myfunction() 
    global $myvar;

有点草率,但确实有效。

【讨论】:

全局变量的悲哀 :(【参考方案11】:

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

就像这里已经说过的最流行的答案一样,您应该使用匿名函数来实现您想做的事情。但是,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.

【讨论】:

【参考方案12】:

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

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

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

【讨论】:

【参考方案13】:

function reset_header() 
    ob_start();

add_action('init', 'reset_header');

然后

reset_header();
wp_redirect( $approvalUrl);

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

【讨论】:

【参考方案14】:

为什么不这么简单:

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

【讨论】:

【参考方案15】:

我已经做了一个代码来发送参数和处理。

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


【讨论】:

如果你要提供一个主要是代码的答案,至少解释一下它的作用。

以上是关于我可以通过 add_action 将参数传递给我的函数吗?的主要内容,如果未能解决你的问题,请参考以下文章

嵌套表单 - 我无法将所有属性参数传递给我的强参数

将对象参数传递给主函数 Java

如何在 Linux 中使用终端命令将文件参数传递给我的 bash 脚本? [复制]

是否可以将自定义参数传递给 android 市场,以便我的应用在首次启动时收到它?

如何通过将参数传递给 URL 来使用 jQuery 刷新页面

将 2 个参数传递给 Laravel 路由 - 资源