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
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 ->
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.
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
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
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);
}
}
add_action
functiondo_action
(if you yourself create actions)wp_localize_script
approach (if you need to pass data to JavaScript)use
in Closures/Anonymous/Lamda functionsadd_filter
, apply_filters
as a transport (clever way)global
or $GLOBALS
(if you are desperate)set_transient
, get_transient
and other functions as a transport (in case of exotic necesities)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 /*, .... */ );
wp_localize_script
approachif 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 <<<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 );
use
in Closures/Anonymous/Lamda functionsif 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
});
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"
add_filter
, apply_filters
as a transportYou 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.
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' );
set_transient
, get_transient
, set_query_var
, get_query_var
as a transportExample #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.
--- Within Ajax handler ---
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.
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.