【问题标题】:can I pass arguments to my function through add_action?我可以通过 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 以某种方式完成的,但如何? :-)

【问题讨论】:

    标签: php wordpress


    【解决方案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 元/插件时,这些页面似乎是很好的参考点 ->

    【讨论】:

    • 如果你不控制对 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种方法

    1. 通过do_action(如果您自己创建操作)
    2. wp_localize_script 方法(如果需要将数据传递给 JavaScript)
    3. 在闭包/匿名/Lamda 函数中使用 use
    4. 使用箭头函数 (PHP 7.4+)
    5. 使用add_filter、apply_filters 作为传输(聪明的方式)
    6. 使用global 或$GLOBALS 破解范围(如果您不顾一切)
    7. 使用set_transient、get_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_filter、apply_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_transient、get_transient、set_query_var、get_query_var 作为传输方式

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

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

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

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

    示例#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);
                    }
                
                }
                

                【讨论】:

                • 如果你要提供一个主要是代码的答案,至少解释一下它的作用。
                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2014-02-15
                • 2011-01-10
                • 2015-04-28
                • 1970-01-01
                • 2020-02-11
                • 2013-01-05
                相关资源
                最近更新 更多