php Warning: Missing argument 2 for {closure}() - php

I have encountered a warning I am not understanding, and I'd like to know in which way this may affect my code. As far as I can tell, the code works and everything looks like it should.
I am working in a WordPress setting, however it seems to me that the problem is a misunderstanding on how to use anonymous function, and not strictly related to WordPress.
However, this is the situation. I have a class with a few methods creating standard pages, which I need to repeat for several instances of that class. The class methods return the content of the page and they work correctly.
I want to add these pages to the wordpress admin menu, and normally I would simply call the function
$t = new My_Class();
//the method of the class that generates the content
$function_name = "foo";
add_submenu_page( $parent_slug, $title, $menu_title , 'manage_options', $function_name, array( $t, $function_name) );
However, in this case the function returns the content instead of echoing it, so that would result in a blank page. So I tried this
add_submenu_page( $parent_slug, $title, $menu_title , 'manage_options', $function_name, function ($t, $function_name ) use ($t, $function_name) {
echo $t->$function_name();
} );
As I said, this works, but it generates that warning and it made me wonder if I am doing something wrong or if I am misunderstanding what the code is doing (thus potentially leading to unwanted behaviours in the future).
PS: I KNOW I could simply add a new method that echoes the content of the other one, or add a parameter to echo the content instead of returning it. However, I'd rather understand what the problem is, if any.

To get rid of the error message do this
add_submenu_page( $parent_slug, $title, $menu_title , 'manage_options', $function_name, function () use ($t, $function_name) {
echo $t->$function_name();
});
I'm not familiar with WP so I don't know what add_submenu_page() does but it seems that it passes one argument to the anonymous function, which you overwrite by adding the same named $t to the anonymous function lexical scope with use ($t, $function_name).
Essentially, second argument to function ($t, $function_name) is not being passed, but in the end it works because you have same variable names, and you overwrite them with the variables 'injected' with the use keyword

Related

How can apply_filters be used to create a filter hook in wordpress?

Wordpress documentation about apply_filters mentions:
It is possible to create new filter hooks by simply calling this function, specifying the name of the new hook using the $hook_name parameter.
Ok, I want to create a filter hook called the_content2, so I do what the docs suggest:
$custom_hook = apply_filters("the_content2", the_content());
Now I assume the_content2 hook is created and is similar to the_content. So on a single post page I should be able to use the_content2 hook like the_content2:
the_content2()
This throws error, function is not defined. I am beginner in wordpress, can someone please explain comprehensively how apply_filters can be used to create your own filters.
Hooks (actions and filters) have two main components, the part that declares the hook, and the callbacks that implement the hook.
A very simple example is:
$name = "Chris";
$name = apply_filters("change_name", $name);
echo $name;
If no one registers a callback, then Chris will be outputted. However, if someone writes this:
add_filter(
"change_name",
function($name){ return "Steve";}
);
Then Steve will be outputted.
At no point, however, will a new function called change_name() be created.
As it relates to hooks, I would generally steer you away from thinking about a hook "being created", and instead think about it as "being called". A function always exists, but hooks are only used if they are actually called.
To your main issue as it relates to the_content(), I would determine what you want to do with that. If you want to transform the result of that function for all instances, a hook is probably a good idea. However, if you just want to use it differently sometimes, a custom function (without a hook) that calls the original, does something and returns it might be more appropriate.
EDIT
Below is a mock of how the hook system works. I've simplified it a bunch, but it should give you a gist of how it works.
function add_filter($name, $callback) {
global $filters;
$filters[$name][] = $callback;
}
function apply_filters($name, $value) {
global $filters;
if(array_key_exists($name, $filters)) {
foreach($filters[$name] as $callback) {
$value = $callback($value);
}
}
return $value;
}
I can't stress this enough, no one is really declaring or registering things. At most, an array key is added with a name when the add_filter/add_action is used. Then, if someone calls the apply_filters/do_action then the key is looked up, and if it exists, the callbacks are run.
So add_filter/add_action has to happen first. It is "I'm interested in XYZ if it actually happens". There's many cases where it might not happen, but if it does, then the callback will fire.
The apply_filters can't/shouldn't throw an error if no one registered a callback, because that is totally a valid case. I often write code that is extensible for future callers but you'll notice that if no one adds a filter, the initial value is returned.

Is there any difference between a class method and a regular function?

I'm trying to learn wordpress to create my wordpress themes. But the problem is, whenever I try to load my css files by using the wp_enqueue_style() inside a class then my wordpress admin area just breaks up. What I mean by breaking is that, it's js file fails to load due to which it's coloring scheme turns from blue to red and functionality of buttons like "Screen Options" or "Help" stops working.
Here is the working code:
function wp_custom_styles(){
wp_enqueue_style("bootstrap_css", get_template_directory_uri() . "/css/bootstrap.min.css");
wp_enqueue_style("style_css", get_stylesheet_uri());
}
add_action("wp_enqueue_scripts", "wp_custom_styles");
But if I use this:
class wp_theme_preparation{
public function __construct(){
add_action("wp_enqueue_scripts", $this->add_theme_styles());
}
public function add_theme_styles(){
wp_enqueue_style("bootstrap_css", get_template_directory_uri() . "/css/bootstrap.min.css");
wp_enqueue_style("style_css", get_stylesheet_uri());
}
}
$instance = new wp_theme_preparation();
The admin area crashes. And it ends like this:
As you can see from the image I clicked on the "Screen Options" button but it doesn't work.
So my question is what is the difference between these two codes ?
Why the first piece of code is working and second isn't when both of them are just calling a function ?
To register an action that is a method, you should use
add_action("wp_enqueue_scripts", array( $this, 'add_theme_styles') );
See the documentation (particularly the 'Using with a class` section).
UPDATE
Your original code
add_action("wp_enqueue_scripts", $this->add_theme_styles());
attempts to register the return value of calling $this->add_theme_styles() as a callback, not what you intended.
WordPress makes use of PHP's call_user_func, which expects a callable argument. From that page:
A PHP function is passed by its name as a string. Any built-in or
user-defined function can be used, except language constructs such as:
array(), echo, empty(), eval(), exit(), isset(), list(), print or
unset().
A method of an instantiated object is passed as an array containing an
object at index 0 and the method name at index 1.
That last sentence comes down to passing array( $objectInstance, 'method_name' ) as the callback.

do_action inside class issue with add_meta_boxes hook

Ok, this is a little specific. I might be missing something but since it killed me enough time , even though I found a way around it, I need to know if there's a way to do it properly.
Basically I want to use add_meta_box (http://codex.wordpress.org/Function_Reference/add_meta_box ) inside a class.
What I am doing:
//an array variable I am trying to pass in the class to a callback function as a parameter
$the_array = array(
'something',
'my meta box'
);
//a class where everything happens
class some_class {
//public function that has the array and initiates the add_meta_boxes hook
public function add_box($class_array) {
//add meta boxes hook to add the meta box properly
add_action('add_meta_boxes', array($this, 'adding_custom_meta_boxes'), 10, 2);
//passing the array variable to the callback function
do_action('add_meta_boxes',$class_array);
}
//the callback function of the add_meta_boxes hook
public function adding_custom_meta_boxes($class_array) {
add_meta_box('my-meta-box', __($class_array[1]), 'render_my_meta_box', 'page', 'normal', 'default');
}
public function render_my_meta_box(){
//the code to generate the html of the meta box goes here
}
}
$class_var = new some_class();
$class_var->add_box($the_array);
I get this error:
Fatal error: Call to undefined function add_meta_box() in C:\xampp\ht.....
but only if I use do_action to pass the variables to the hook callback function
I found a way around it with global variables, but , does anybody know a correct way of doing this?
I am trying to create the meta box from inside a class and this happens. It works well from outside a class. Anybody any ideas?
your not too far off. to correct the above change to this:
public function adding_custom_meta_boxes($class_array) {
add_meta_box('my-meta-box', __($class_array[1]), array($this, 'render_my_meta_box'), 'page', 'normal', 'default');
}
remove "do_action"
do_action tells the script to perform the attached actions right now and the function add_meta_boxes has yet to load (google the load process for wp functions). Thats the whole point of add_actions / Filters!

Access variable in defined in a function outside of that function

Firstly: I know this has been asked before, but I've looked through a lot of questions/answers and I can't work out how to get any of them working. So, sorry about that.
So basically I'm writing some functions/shortcodes in Wordpress that mean that I can use a shortcode to publish Vine videos to a Wordpress blog:
function embedVine($atts) {
extract(shortcode_atts(array(
"id" => ''
), $atts));
$vine_id = $id;
// I'm then doing a whole load of stuff involving $vine_id, including using it as a parameter to pass to different functions I've written that are separate to this function.
// I should also mention that $vine_id is the id on the end of a Vine URL.
} add_shortcode("vine", "embedVine");
A user can then use the [vine id="..."] shortcode in the Wordpress editor.
I then have a function I've written but I don't want to execute it inside of the function above, otherwise it will run every time the function/shortcode runs which wouldn't be good. I instead need to execute it outside of the function but still use $vine_id as a parameter for it. However, as $vine_id was defined inside the function above, I cannot access it outside of the function.
Here is the second function:
function vineThumb($id) {
$vine = file_get_contents("http://vine.co/v/{$id}");
return $vine;
// of course, it's a lot more complicated than this but for the sake of this, it works.
} vineThumb($vine_id);
Executing the function would return http://vine.co/v/{$vine_id}. How would I make the $vine_id function accessible outside of the shortcode function (the first one)?
Hope I've explained that clearly enough, I'm not a PHP programmer as you can probably tell but I know enough to get by. This sort has me stumped though. Thanks for any help :)
I don't know if those two functions are located in the same file but try this. http://www.php.net/manual/en/language.variables.scope.php
$vine_id = null; //Define it outside the function
function embedVine($atts) {
global $vine_id; //Refers to $vine_id outside the function
extract(shortcode_atts(array(
"id" => ''
), $atts));
$vine_id = $id; //$vine_id now has the value of $id when embedVine exits
} add_shortcode("vine", "embedVine");

Custom hooks in WordPress across plugins

I'm trying to create a hook in one Wordpress plugin that could be used by other plugins. First off, is this even possible? I'm also sending some additional args so this may be 2 questions in one since I've been having trouble finding definitive information on how to do this.
Here is what I've tried so far:
In the plugin that is creating the hook (call it Plugin 1) I added:
do_action('plugin1_hook', $customArg1, $customArg2, $customArg3);
at the point that I want the hook to fire. Then, in a different plugin (Plugin 2), I added:
add_action('plugin1_hook', 'my_function');
and
function my_function($customArg1, $customArg2, $customArg3) { //my code }
This does not seem to be firing the function, however.
My refence for this has been the Wordpress hook comment_post, which is defined by Wordpress as:
do_action('comment_post', $comment_ID, $commentdata['comment_approved']);
and I am using as:
add_action('comment_post', 'my_comment');
function my_comment($comment_id) { //my code }
The above snippet is functioning properly.
I thought I'd post this as an answer as it's a little clearer to explain :)
When you hook a function, but do not specify the number of arguments, WordPress will always pass back one argument.
You won't get errors for something like this;
function do_my_hook($arg1, $arg2 = '', $arg3 = '') {}
add_action('my_hook', 'do_my_hook');
But you will for something like this;
function do_my_hook($arg1, $arg2, $arg3) {}
add_action('my_hook', 'do_my_hook');
WordPress is trying to call do_my_hook(), but it's only passing back one argument. The first example uses PHP default function arguments, so that you can call a function without passing all available arguments, but without error.
The second example will trigger a 'missing argument(s)' PHP error, as all three arguments are required.
The fix?
add_action('my_hook', 'do_my_hook', 10, 3);
The idea behind defining how many arguments your function takes is to avoid errors like these (though technically they are as easily avoided using default arguments!).
My guess is the second plugin is loading after the first one, so the hook has already fired by the time you add an action to it. You might try this for the first plugin:
function my_custom_hook_insertion($arg1, $arg2, $arg3){
do_action('plugin1_hook', $arg1, $arg2, $arg3);
}
add_action('plugins_loaded', 'my_custom_hook_insertion');
That will wait until all plugins are loaded before firing the hook.
Changing my add_action to this fixed the problem:
add_action('plugin1_hook', 'my_function', 10, 3);
The 10 represents the priority, and the 3 represents the number of args that the function will take. I'm not exactly sure how the matching works, since the default is 1, and I use plenty of hooks without specifying 0 args and I've used hooks that pass more than 1 arg but only used 1 arg in my function signature. Source: WordPress Codex: Function Reference/add action
It is working though, so cross plugin hooks are possible.

Categories