I know there are several posts on this topic. I have followed many of them as well as other resources on the web and thought I had it down, but it does not seem to be working. In my case, I have 2 functions hooked to 2 separate actions that need the same data.
$data = array('red', 'green', 'blue');
do_action('use_colors_here', $data);
add_action('wp_body_open', 'use_colors_here', 10, 1);
function use_colors_here($data) {
$out = '<h1>Colors</h1>';
$out .= '<p>Color 1: ' . $data[1] . '</p>';
$out .= '<p>Color 2: ' . $data[2] . '</p>';
echo $out;
}
do_action('use_colors_there', $data);
add_action('wp_enqueue_scripts', 'use_colors_there', 10, 1);
function use_colors_there($data) {
wp_enqueue_script('color-script-1', get_stylesheet_directory_uri() . '/js/colors_' . $data[1] . '.js');
wp_enqueue_script('color-script-2', get_stylesheet_directory_uri() . '/js/colors_' . $data[2] . '.js');
}
The expected behavior was for the values of $data[1]
and $data[2]
(green and blue respectively) to be accessible by the 2 functions and printed out in the markup each is responsible for adding to the page. Unfortunately, $data
was not accessible inside the functions and I end up with markup looking like:
<h1>Colors</h1>
<p>Color 1: </p>
<p>Color 2: </p>
What am I doing wrong?
UPDATE
After reading a bit closer, I see that I have to use the hook rather than the function name as the 1st argument of do_action
. So I changed it to:
do_action('wp_body_open', $data);
and it seems to be working.
FINAL CODE (using accepted answer)
function get_component_config() {
return ['red', 'green', 'blue'];
}
add_action('wp_body_open', 'use_colors_here');
function use_colors_here() {
$data = get_component_config();
$out = '<h1>Colors</h1>';
$out .= '<p>Color 1: ' . $data[1] . '</p>';
$out .= '<p>Color 2: ' . $data[2] . '</p>';
echo $out;
}
add_action('wp_enqueue_scripts', 'use_colors_there');
function use_colors_there() {
$data = get_component_config();
wp_enqueue_script('color-script-1', get_stylesheet_directory_uri() . '/js/colors_' . $data[1] . '.js');
wp_enqueue_script('color-script-2', get_stylesheet_directory_uri() . '/js/colors_' . $data[2] . '.js');
}
I know there are several posts on this topic. I have followed many of them as well as other resources on the web and thought I had it down, but it does not seem to be working. In my case, I have 2 functions hooked to 2 separate actions that need the same data.
$data = array('red', 'green', 'blue');
do_action('use_colors_here', $data);
add_action('wp_body_open', 'use_colors_here', 10, 1);
function use_colors_here($data) {
$out = '<h1>Colors</h1>';
$out .= '<p>Color 1: ' . $data[1] . '</p>';
$out .= '<p>Color 2: ' . $data[2] . '</p>';
echo $out;
}
do_action('use_colors_there', $data);
add_action('wp_enqueue_scripts', 'use_colors_there', 10, 1);
function use_colors_there($data) {
wp_enqueue_script('color-script-1', get_stylesheet_directory_uri() . '/js/colors_' . $data[1] . '.js');
wp_enqueue_script('color-script-2', get_stylesheet_directory_uri() . '/js/colors_' . $data[2] . '.js');
}
The expected behavior was for the values of $data[1]
and $data[2]
(green and blue respectively) to be accessible by the 2 functions and printed out in the markup each is responsible for adding to the page. Unfortunately, $data
was not accessible inside the functions and I end up with markup looking like:
<h1>Colors</h1>
<p>Color 1: </p>
<p>Color 2: </p>
What am I doing wrong?
UPDATE
After reading a bit closer, I see that I have to use the hook rather than the function name as the 1st argument of do_action
. So I changed it to:
do_action('wp_body_open', $data);
and it seems to be working.
FINAL CODE (using accepted answer)
function get_component_config() {
return ['red', 'green', 'blue'];
}
add_action('wp_body_open', 'use_colors_here');
function use_colors_here() {
$data = get_component_config();
$out = '<h1>Colors</h1>';
$out .= '<p>Color 1: ' . $data[1] . '</p>';
$out .= '<p>Color 2: ' . $data[2] . '</p>';
echo $out;
}
add_action('wp_enqueue_scripts', 'use_colors_there');
function use_colors_there() {
$data = get_component_config();
wp_enqueue_script('color-script-1', get_stylesheet_directory_uri() . '/js/colors_' . $data[1] . '.js');
wp_enqueue_script('color-script-2', get_stylesheet_directory_uri() . '/js/colors_' . $data[2] . '.js');
}
Share
Improve this question
edited Feb 10, 2021 at 8:12
Daveh0
asked Feb 9, 2021 at 9:19
Daveh0Daveh0
1912 silver badges13 bronze badges
3
|
1 Answer
Reset to default 0You have an action hook named use_colors_here
and you run the hook using do_action( 'use_colors_here', $data )
, but I don't see where you call add_action()
for that hook?
I mean, the do_action()
and add_action()
should be used like so:
// This adds a callback to the use_colors_here hook.
add_action( 'use_colors_here', 'some_function' );
// And this is the callback which accepts one parameter from the use_colors_here hook.
function some_function( $data ) {
var_dump( $data );
}
// And this do_action() executes the above callback (and other callbacks added to the
// `use_colors_here` hook).
$data = array( 'red', 'green', 'blue' );
do_action( 'use_colors_here', $data );
UPDATE (revised)
I see that I have to use the hook rather than the function name as the 1st argument of
do_action
Yes that's right, the first parameter for do_action()
is indeed the hook name, whereas the second and the rest of parameters are the parameters passed to the hook callbacks — but in the case of two or more parameters, you need to use the 4th parameter for add_action()
to specify the number of parameters that your callback accepts.
// This fires the some_hook hook which has two parameters.
do_action( 'some_hook', 'param 1', 'param 2' );
// So when adding your action, if you want (to access) both the above parameters
// from your callback, then you must set the 4th parameter below to 2.
add_action( 'some_hook', 'some_function', 10, 2 );
function some_function( $param1, $param2 ) {
var_dump( $param1, $param2 );
}
And do_action()
(although indirectly) actually uses call_user_func_array()
to run the actions for a specific (action) hook, or to run the callbacks registered to run on that hook, so if you understand how call_user_func_array()
works, then you'd also understand how do_action()
works.
function my_callback( $foo, $bar ) {
var_dump( $foo, $bar, __FUNCTION__ );
}
$data = 'using call_user_func_array()';
// this calls my_callback() directly
call_user_func_array( 'my_callback', array( $data, 'second param' ) );
add_action( 'hook_name', 'my_callback', 10, 2 );
$data = 'using do_action()';
// but this fires the "event"/hook named hook_name and then it calls
// my_callback() indirectly via call_user_func_array()
// i.e. it calls call_user_func_array( 'my_callback', array( $data, 'yay, it works!' ) )
do_action( 'hook_name', $data, 'yay, it works!' );
I just need to be able to access
$data
from inside my 2 functions,use_colors_here
anduse_color_there
Then you're doing it correctly, i.e. when you do do_action('wp_body_open', $data)
, the $data
will be passed to your 2 functions (and all other actions/callbacks for the hook).
But without calling do_action()
manually and without using the global
keyword or even $GLOBALS
, the other possible way to access the $data
variable is by using a closure; however, the drawback is that it'll be next to impossible to remove the specific action using remove_action()
— because closures are anonymous functions, so what name would we use when removing the action?
add_action( 'some_hook', 'some_function', 10, 2 );
// that can be easily removed like so:
remove_action( 'some_hook', 'some_function', 10 );
$data = array( 'red', 'green', 'blue' );
add_action( 'some_hook', function () use ( $data ) {
var_dump( $data );
} );
// now with that one, how do we remove it?
//remove_action( 'some_hook', ??, 10 );
Therefore, if you just wanted to get access to the data in the $data
, then you could use a custom function which returns the data:
function get_colors() {
return array( 'red', 'green', 'blue' );
}
add_action( 'wp_body_open', 'use_colors_here' );
function use_colors_here() {
$data = get_colors();
var_dump( $data );
}
I thought it would be better to keep everything in
functions.php
rather than adding more code toheader.php
... just for organizational purposes.
Yes (although not exactly "everything"), I thought the same as well. But in my original "Update" section, I was just saying you could (or that it's just fine if you) explicitly call your actions after the hook is fired. I.e.
// Let's say you define $data here. (in same file or block of code)
$data = array( 'red', 'green', 'blue' );
// So instead of..
do_action( 'wp_body_open', $data );
// You can do..
wp_body_open(); // this fires the wp_body_open hook
use_colors_here( $data );
// But that means, use_colors_here() should no longer be hooked on to the hook.
Does calling the function directly in
header.php
have any significant performance advantages?
No, but calling it directly means you can easily pass the $data
and other parameters..
Otherwise, for local variables like the $data
above, then we would need to use a closure in order to access the variable (and eventually the data inside or referenced to by that variable).
use_colors_here
but no functions were added to that action so it does nothing. Then you have a function with that same name added to an unrelated actionwp_body_open
, but you try to use a$data
argument, butwp_body_open
does not provide any arguments! And then, you fire off a 3rd actionuse_colors_there
that has nothing added to it either, so that doesn't do anything ( was this a typo? _there? _here? ). – Tom J Nowell ♦ Commented Feb 9, 2021 at 10:18use_colors_there
function, but it's not used anywhere – Tom J Nowell ♦ Commented Feb 9, 2021 at 10:23add_action
. I'm trying to pass$data
to both functions,use_colors_here
anduse_colors_there
, which hook towp_body_open
andwp_enqueue_scripts
respectively. – Daveh0 Commented Feb 9, 2021 at 10:30