0

I'm using the Wordpress boilerplate to develop a plugin. At some point, I wanted to make dynamic functions with some external parameters when using $this->loader->add_action() so I used an anonymous function... but it doesn't work. So I resolved to bypass the loader and use the Wordpress standard add_action() and it works! But I know it's not good practice. How to pass an anonymous function through the loader? I'd like to know if any of you have a idea of how to implement this with the loader.

What I tried

$this->loader->add_action("views_edit-{$post_type}", $plugin_admin, function($views) use ($plugin_admin, $post_type) { return $plugin_admin->some_function($views, $post_type); }); 

The error I get

 Your PHP code changes were rolled back due to an error on line 959 of file wp-includes/plugin.php. Please fix and try saving again. Uncaught Error: Object of class Closure could not be converted to string in wp-includes/plugin.php:959 Stack trace: #0 wp-includes/class-wp-hook.php(74): _wp_filter_build_unique_id() #1 wp-includes/plugin.php(121): WP_Hook->add_filter() #2 wp-includes/plugin.php(399): add_filter() #3 wp-content/plugins/myplugin/includes/class-myplugin-loader.php(124): add_action() #4 wp-content/plugins/myplugin/includes/class-myplugin.php(266): MyPlugin_Loader->run() #5 wp-content/plugins/myplugin/myplugin.php(76): MyPlugin->run() #6 wp-content/plugins/myplugin/myplugin.php(79): run_myplugin() #7 wp-settings.php(418): include_once('/home/...') #8 wp-config.php(106): require_once('/home/...') #9 wp-load.php(50): require_once('/home/...') #10 wp-admin/admin.php(34): require_once('/home/...') #11 wp-admin/plugin-editor.php(10): require_once('/home/...') #12 {main} thrown 

What I used instead by bypassing the loader (it works)

add_action("views_edit-{$post_type}", function($views) use ($plugin_admin, $post_type) { return $plugin_admin->some_function($views, $post_type); }); 
3
  • 1
    unfortunately this boilerplate framework doesn't support closures - the 2nd parameter MUST be an object, and the 3rd parameter MUST be a string representing a publicly accessible method available on the object provided in the 2nd parameter. To use the boilerplate approach, the siimplest solution is create a dedicated class with a method you can use in place of your anonymous function. I suppose you could use an anonymous class (php.net/manual/en/language.oop5.anonymous.php) but this would complicate things. Just create a class to do your work, and hook that in. Why not? Commented Mar 20, 2022 at 13:09
  • Thank you for your fast reply. I didn't know the boilerplate doesn't support closures, thanks for the clarification. As for your suggestion, even if I created a dedicated class to replace the anonymous function, I don't see where I could pass arguments through the loader since their is no parameter where to pass them? Commented Mar 20, 2022 at 21:32
  • Do you mean I should create a class where I pass the arguments I want to pass, then call that class in the 2nd parameter of the loader (object) and then call a function name inside that class as a 3rd parameter of the loader (string)? Commented Mar 20, 2022 at 21:40

1 Answer 1

0

Thanks Paul, you led me to the solution.

What I did

In class-mypluging-admin.php, I added this:

/** * Additional arguments for this plugin. * * @since 1.0.0 * @access private * @var array $args The current arguments of this plugin. */ private $args; /** * Initialize the class and set its properties. * * @since 1.0.0 * @param string $plugin_name The name of this plugin. * @param string $version The version of this plugin. * @param array $args The additional arguments of this plugin. */ public function __construct( $plugin_name, $version, $args = null ) { $this->plugin_name = $plugin_name; $this->version = $version; $this->args = $args; } 

Then for the functions in class-mypluging-admin.php

function some_function( $views ) { $post_type = $this->args['post_type']; ... } 

In class-mypluging.php, I do this:

foreach($post_types as $post_type) { $args = array( 'post_type' => $post_type, ); $plugin_admin = new MyPlugin_Admin( $this->get_plugin_name(), $this->get_version(), $args ); $this->loader->add_action("views_edit-{$post_type}", $plugin_admin, 'some_function'); } 

And it works! Is that the correct way to do this?

2
  • So my solution is actually flawed. 😔 since the loader fire the actions afterwards, it only uses the last assignment of the $args. I can't make it work with loops where I change dynamically the value of the $args. Commented Mar 21, 2022 at 23:47
  • Ok so, in order to make the $args change dynamically inside the loop, I instantiate a new $plugin_admin inside the loop. I edited my anwer accordingy. It works but I have absolutely no clue if it's a clean way or not to do so. So I'd appreciate a confirmation. 🙂 Commented Mar 22, 2022 at 1:24

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.